package StringAlgorithms;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

class SuffixTree1590
{	private char[] Text;
	private int[] SuffixLink;
	private int nodeCount;
	private Map<Key,Edge> M;
	
	private static class Key
	{	private int nid;
		private char c;
		
		public Key(int id,char _c)
		{	nid=id;c=_c;
		}
		public static Key MakeKey(Edge e,char c)
		{	return new Key(e.sNode,c);
		}
		@Override
		public int hashCode()
		{	return nid*100+(int)c;
		}
		@Override
		public boolean equals(Object k)
		{	return (nid==((Key)k).nid && c==((Key)k).c);
		}
	}
	public class Edge
	{	public int fcIndex,lcIndex,sNode,eNode;
	
		public Edge(int fci,int lci,int pNode)
		{	fcIndex=fci;lcIndex=lci;
			sNode=pNode;eNode=++nodeCount;
		}
	}
	private class InPath
	{	public int oriNode,fcIndex,lcIndex;
		
		public InPath(int oN,int fci,int lci)
		{	oriNode=oN;fcIndex=fci;lcIndex=lci;
		}
		public boolean isExplicit()
		{	return fcIndex>lcIndex;
		}
		public boolean isImplicit()
		{	return fcIndex<=lcIndex;
		}
		public void Canonize()
		{	if (isImplicit())
			{	Edge e=M.get(new Key(oriNode,Text[fcIndex]));
				int eSpan=e.lcIndex-e.fcIndex;
				while (eSpan<=lcIndex-fcIndex)
				{	fcIndex+=eSpan+1;
					oriNode=e.eNode;
					if (fcIndex<=lcIndex)
					{	e=M.get(new Key(oriNode,Text[fcIndex]));
						eSpan=e.lcIndex-e.fcIndex;
					}
				}
			}
		}
	}
	
	public SuffixTree1590(char[] Input)
	{	nodeCount=0;
		Text=Input;
		SuffixLink=new int[2*Text.length];Arrays.fill(SuffixLink,-1);
		M=new HashMap<Key,Edge>(2*Text.length);
	}
	private int SplitEdge(Edge e,InPath p)
	{	M.remove(Key.MakeKey(e,Text[e.fcIndex]));
		
		Edge newEdge=new Edge(e.fcIndex,e.fcIndex+p.lcIndex-p.fcIndex,p.oriNode);
		M.put(Key.MakeKey(newEdge,Text[p.fcIndex]),newEdge);
		SuffixLink[newEdge.eNode]=p.oriNode;
		
		e.sNode=newEdge.eNode;
		e.fcIndex+=p.lcIndex-p.fcIndex+1;
		M.put(Key.MakeKey(e,Text[e.fcIndex]),e);
		
		return newEdge.eNode;
	}
	private void AddPrefix(InPath wkNode,int curCharId)
	{	int parentNode,lastParentNode=-1;
		while (true)
		{	parentNode=wkNode.oriNode;
			if (wkNode.isExplicit())
			{	if (M.containsKey(new Key(wkNode.oriNode,Text[curCharId])))
					break;
			}
			else
			{	Edge focus=M.get(new Key(wkNode.oriNode,Text[wkNode.fcIndex]));
				if (Text[focus.fcIndex+(wkNode.lcIndex-wkNode.fcIndex)+1]==Text[curCharId])
					break;
				parentNode=SplitEdge(focus,wkNode);
			}
			Edge newEdge=new Edge(curCharId,Text.length-1,parentNode);
			M.put(Key.MakeKey(newEdge,Text[curCharId]),newEdge);
			
			if (lastParentNode>0) SuffixLink[lastParentNode]=parentNode;
			lastParentNode=parentNode;
			
			if (wkNode.oriNode==0)
				wkNode.fcIndex++;
			else
				wkNode.oriNode=SuffixLink[wkNode.oriNode];
			wkNode.Canonize();
		}
		if (lastParentNode>0) SuffixLink[lastParentNode]=parentNode;
		lastParentNode=parentNode;
		wkNode.lcIndex++;
		wkNode.Canonize();
	}
	public void MakeTree()
	{	InPath root=new InPath(0,0,-1);SuffixLink[0]=-1;
		for (int i=0;i<=Text.length-1;i++)
			AddPrefix(root,i);
	}
	public Map<Key,Edge> getMap()
	{	return M;
	}
}
class Solver1590
{	private char[] Text;

	public void Solve() throws IOException
	{	StreamTokenizer in=new StreamTokenizer(new InputStreamReader(System.in));
		in.nextToken();Text=in.sval.toCharArray();
		
		int rs=0;
		SuffixTree1590 sfTree=new SuffixTree1590(Text);
		sfTree.MakeTree();
		for (SuffixTree1590.Edge e:sfTree.getMap().values())
			rs+=(e.lcIndex-e.fcIndex+1);
		System.out.println(rs);
	}
}
public class P1590
{	public static void main(String[] args) throws IOException
	{	Solver1590 solver=new Solver1590();
		solver.Solve();
	}
}
